package services;

import java.util.Collection;
import java.util.HashSet;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import repositories.UserRepository;
import security.Authority;
import security.LoginService;
import security.UserAccount;
import domain.Project;
import domain.Registration;
import domain.User;
import domain.UserGroup;
import forms.UserForm;

@Service
@Transactional
public class UserService {

	// Managed Repository

	@Autowired
	private UserRepository userRepository;

	// Supporting Services
	
	@Autowired
	private AdministratorService administratorService;

	// Constructors

	public UserService() {
		super();
	}

	// Simple CRUD methods
	public User create() {
		User result;
		UserAccount userAccount;
		Authority authority;
		Collection<Project> createdProjects;
		Collection<Project> followedProjects;
		Collection<Registration> registrations;
		UserGroup userGroup;

		authority = new Authority();
		createdProjects = new HashSet<Project>();
		followedProjects = new HashSet<Project>();
		registrations = new HashSet<Registration>();
		userGroup = new UserGroup();

		userAccount = new UserAccount();
		authority.setAuthority("USER");
		userAccount.addAuthority(authority);

		result = new User();
		result.setUserAccount(userAccount);
		result.setCreatedProjects(createdProjects);
		result.setFollowedProjects(followedProjects);
		result.setRegistrations(registrations);
		result.setUserGroup(userGroup);

		return result;
	}

	public Collection<User> findAll() {
		Collection<User> result;

		result = userRepository.findAll();

		return result;
	}

	public User findOne(int userId) {
		User result;

		result = userRepository.findOne(userId);

		return result;
	}

	public void save(User user) {
		Assert.notNull(user);
		Assert.notNull(user.getUserGroup());
		if(user.getId()==0){
			Assert.isNull(findByUsername(user.getUserAccount().getUsername()));
		}
		Assert.isNull(administratorService.findByUsername(user.getUserAccount().getUsername()));


		userRepository.save(user);
	}

	// Other Business Methods
	public User findByPrincipal() {
		User result;
		UserAccount userAccount;

		userAccount = LoginService.getPrincipal();
		Assert.notNull(userAccount);

		result = findByUserAccount(userAccount);
		Assert.notNull(result);

		return result;
	}

	public User findByUserAccount(UserAccount userAccount) {
		Assert.notNull(userAccount);
		User result;

		result = userRepository.findByUserAccountId(userAccount.getId());
		
		return result;
	}
	
	public User findByUsername (String username){
		Assert.notNull(username);
		User result;
		result = userRepository.findByUsername(username);
		return result;
	}

	// Reconstruction method
	public User reconstruct(UserForm userForm) {
		Assert.notNull(userForm);
		User result;
		Md5PasswordEncoder encoder = new Md5PasswordEncoder();
		String password = userForm.getPassword();
		String hash = encoder.encodePassword(password, null);

		result = create();
		result.getUserAccount().setUsername(userForm.getUsername());
		result.getUserAccount().setPassword(hash);
		result.setName(userForm.getName());
		result.setSurname(userForm.getSurname());
		result.setEmail(userForm.getEmail());
		
		result.setUserGroup(userForm.getUserGroup());

		return result;
	}
}
